#include <iostream>
#include <unistd.h>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> //sockaddr_in 在里面
#include <arpa/inet.h>
#include <cstring>

#include "Common.hpp"

static const int BUFFER_SIZE = 1024;
static const int Default_Max_cnt = 5;
static const int Default_interval=1;

int main(int argc, char *args[])
{
    if (argc != 3)
    {
        std::cout << "参数错误" << std::endl;
        Die(USAGE_ERR);
    }

    std::string ip = args[1];
    uint16_t port = std::stoi(args[2]);

    // 2.创建结构体 && 填写服务器参数用于发送信息
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = inet_addr(ip.c_str());

    // client 不需要bind UDP中 sendto 自动帮我们bind了
    // 前面套路都是一样的，不过这里需要connet向服务器发起一个连接，这个时候connect会自动帮我们bind
    int flag=1;
    int socketfd = -1;
    do
    {
        int cnt = 0;
        int interval =Default_interval;
        do
        {
            // 1.创建套接字
            if(socketfd!=-1) close(socketfd);
            socketfd = socket(AF_INET, SOCK_STREAM, 0);
            if (socketfd < 0)
            {
                std::cerr << "socket error" << std::endl;
                Die(SOCKET_ERR);
            }
            // std::cerr<<"connect error"<<std::endl;
            // Die(CONNECT_ERR);
            int n = connect(socketfd, CONV(&server), sizeof(server));
            if (n < 0)
            {
                cnt++;
                std::cout << "connect error reconnect cnt: " << cnt << std::endl;
                sleep(interval);
            }
            else
                break;
        } while (cnt < Default_Max_cnt);

        if (cnt >= Default_Max_cnt)
        {
            std::cerr << "connect error" << std::endl;
            Die(CONNECT_ERR);
        }
        // 用于 Client say
        std::string message;
        while (true)
        {
            char buffer[BUFFER_SIZE];
            std::cout << "client say# ";
            std::getline(std::cin, message);
            // if(message.size())  message+='\n';  // 确保打印到缓冲区的时候可以刷新，缓冲区为行刷新
            int n = ::write(socketfd, message.c_str(), message.size());
            if (n > 0)
            {
                int m = ::read(socketfd, buffer, sizeof(buffer) - 1);
                if (m > 0)
                {
                    buffer[m] = 0;
                    std::cout << buffer;
                }
                else break;
            }
            else if (n == 0)
            {
                flag=0;
                break;
            }
            else 
                 break;
        }
    }while(flag);
    ::close(socketfd); // 别忘了关闭文件描述符
    return 0;
}